#pragma once
#include <iostream>
#include <unistd.h>
using namespace std;

class Date
{    
    friend ostream& operator<<(ostream& out, const Date& d);
    friend istream& operator>>(istream& in, Date& d);
public:
    Date(){}

    Date(int year, int month, int day) : _year(year), _month(month), _day(day)
    {}

    Date(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }

    Date& operator=(const Date& d)
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;

        return *this;
    }

    int countDay() const
    {
        Date tmp(1900, 1, 1);
        int cnt = 1;
        while(tmp != *this)
        {
            ++cnt;
            ++tmp._day;
            if(tmp._day == tmp.GetMonthDay()+1)
            {
                ++tmp._month;
                tmp._day = 1;
                if(tmp._month == 13)
                {
                    ++tmp._year;
                    tmp._month = 1;
                }
            }
        }
        return cnt;
    }

    //日期-日期
    int operator-(const Date& d)
    {
        return countDay() - d.countDay();
    }

    //日期+=天数
    Date& operator+=(int day)
    {
        if(day < 0)
        {
            return *this -= -day;
        }
        while(day--)
        {
            _day++;
            if(_day == GetMonthDay() + 1)
            {
                _day = 1;
                _month++;
                if(_month == 13)
                {
                    _month = 1;
                    _year++;
                }
            }
        }

        return *this;
    }

    //日期-=天数
    Date& operator-=(int day)
    {
        if(day < 0)
        {
            return *this += -day;
        }
        while(day--)
        {
            _day--;
            if(_day == 0)
            {
                _month--;
                if(_month == 0)
                {
                    _year--;
                    _month = 12;
                }
                _day = GetMonthDay();
            }
        }
        return *this;
    }

    //日期+天数
    Date operator+(int day)
    {
        Date tmp(*this);
        tmp += day;
        
        return tmp;
    }

    //日期-天数
    Date operator-(int day)
    {
        Date tmp(*this);
        tmp -= day;

        return tmp;
    }

    //获取今天是星期几
    const char* GetWeekDay()
    {
        const char* weekday[8] = {"hello", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"};
        Date d(1970, 1, 5);
        int tmp = *this-d;

        return weekday[tmp%7+1]; 
    }

    //今天是今年的第多少天
    int GetDay()
    {
        Date tmp(_year, 1, 1);
        
        return tmp-*this+1;
    }

    //前置++
    Date& operator++()
    {
        *this += 1;
        return *this;   
    }

    //后置++
    Date operator++(int)
    {
        Date tmp(*this);
        *this += 1;
        return tmp;
    }

    //前置--
    Date& operator--()
    {
        *this -= 1;
        return *this;
    }

    //后置--
    Date operator--(int)
    {
        Date tmp(*this);
        *this -= 1;

        return tmp;
    }

    void Show() const
    {
        cout << _year << "-" << _month << "-" << _day << endl;
    }

    //比较日期大小
    bool operator==(const Date& d) const
    {
        return _year == d._year && _month == d._month && _day == d._day;
    }

    bool operator!=(const Date& d) const
    {
        return !(*this == d);
    }

    bool operator>(const Date& d) const
    {
        if(_year > d._year)
            return true;
        else if(_year == d._year && _month > d._month)
            return true;
        else if(_year == d._year && _month == d._month && _day > d._day)
            return true;
        else
            return false;
    }

    bool operator<(const Date& d) const 
    {
        return !(*this >= d);
    }

    bool operator>=(const Date& d) const
    {
        return *this > d || *this == d;
    }

    bool operator<=(const Date& d) const 
    {
        return !(*this > d);
    }
private:
    int GetMonthDay()
    {
        int day[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if(_year % 400 == 0 || (_year % 100 != 0 && _year % 4 == 0))
        {
            day[2]++;
        }

        return day[_month];
    }
private:
    int _year;
    int _month;
    int _day;
};

ostream& operator<<(ostream& out, const Date& d)
{
    out << d._year << "-" << d._month << "-" << d._day;

    return out;
}

istream& operator>>(istream& in, Date& d)
{
    in >> d._year >> d._month >> d._day;

    return in;
}